/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { HttpUrl } from '../HttpUrl';
import connection from '@ohos.net.connection';
import StringUtil  from './StringUtil';
import { Logger } from './Logger';

export const TimeUnit = {
    SECONDS: 'seconds',
    MINUTES: 'minutes'
};

export const TimeoutType = {
    CONNECT: 'connect',
    READ: 'read',
    WRITE: 'write'
};

export class Utils {
     static  VERIFY_AS_IP_ADDRESS:string =  "([0-9a-fA-F]*:[0-9a-fA-F:.]*)|([\\d.]+)";

    public static getDomainOrIp(url: string): string {
        let result = "";
        let j = 0, startIndex = 0, endIndex = 0;
        for (let i = 0; i < url.length; i++) {
            if (url.charAt(i) == '/') {
                j++;
                if (j == 2)
                startIndex = i;
                else if (j == 3)
                endIndex = i;
            }

        }
        result = url.substring(startIndex + 1, endIndex == 0 ? url.length : endIndex);
        return result;
    }

    /**
     * Increments {@code pos} until {@code input[pos]} is not ASCII whitespace. Stops at {@code
     * limit}.
     */
    static indexOfFirstNonAsciiWhitespace(input: string, startIndex: number, endIndex: number): number {
        for (var i = startIndex; i < endIndex; i++) {
            switch (input.charAt(i)) {
                case '\t':
                case '\n':
                case '\u000C':
                case '\r':
                case ' ':
                    continue;
                default:
                    return i;
            }
        }
        return endIndex;
    }

    /**
     * Decrements {@code limit} until {@code input[limit - 1]} is not ASCII whitespace. Stops at
     * {@code pos}.
     */
    static indexOfLastNonAsciiWhitespace(input: string, startIndex: number, endIndex: number): number {
        for (var i = endIndex - 1; i >= startIndex; i--) {
            switch (input.charAt(i)) {
                case '\t':
                case '\n':
                case '\u000C':
                case '\r':
                case ' ':
                    continue;
                default:
                    return i + 1;
            }
        }
        return startIndex;
    }

    /** Returns true if an HTTP request for {@code a} and {@code b} can reuse a connection. */
    static canReuseConnectionFor(a: HttpUrl, b: HttpUrl): boolean {
        Logger.info('a url() = ' + a.getUrl()+"  host"+a.getHost()+"  port"+a.getPort()+"  Scheme"+a.getScheme())
        Logger.info('b url() = ' + b.getUrl()+"  host"+b.getHost()+"  port"+b.getPort()+"  Scheme"+b.getScheme())

        return a.getHost() == b.getHost()
        && a.getPort() == b.getPort()
        && a.getScheme() == b.getScheme();
    }

  /**
   * Returns the index of the first character in {@code input} that contains a character in {@code
   * delimiters}. Returns limit if there is no such character.
   */
  static delimiterOffset(input: string, pos: number, limit: number, delimiters: string): number {
    for (var i = pos; i < limit; i++) {
      if (delimiters.indexOf(input.charAt(i)) != -1) return i;
    }
    return limit;
  }

  /**
   * 将ArrayBuffer 转换成string
   * @param buf ArrayBuffer
   */
  public static Utf8ArrayToStr(buf: ArrayBuffer) {
    return String.fromCharCode.apply(null, new Uint8Array(buf))
  }

  //字符串转ArrayBuff
  public static strToArrayBuffer(str) {
    var bytes = new Array();
    var len, c;
    len = str.length;
    for (var i = 0; i < len; i++) {
      c = str.charCodeAt(i);
      if (c >= 0x010000 && c <= 0x10FFFF) {
        bytes.push(((c >> 18) & 0x07) | 0xF0);
        bytes.push(((c >> 12) & 0x3F) | 0x80);
        bytes.push(((c >> 6) & 0x3F) | 0x80);
        bytes.push((c & 0x3F) | 0x80);
      } else if (c >= 0x000800 && c <= 0x00FFFF) {
        bytes.push(((c >> 12) & 0x0F) | 0xE0);
        bytes.push(((c >> 6) & 0x3F) | 0x80);
        bytes.push((c & 0x3F) | 0x80);
      } else if (c >= 0x000080 && c <= 0x0007FF) {
        bytes.push(((c >> 6) & 0x1F) | 0xC0);
        bytes.push((c & 0x3F) | 0x80);
      } else {
        bytes.push(c & 0xFF);
      }
    }
    var array = new Int8Array(bytes.length);
    for (var i = 0; i <= bytes.length; i++) {
      array[i] = bytes[i];
    }
    return array.buffer;
  }

  public static arrayUnrepeated(arr: Array<connection.NetAddress>): Array<connection.NetAddress> {
    let result = new Array<connection.NetAddress>()
    let preAddress: string
    for (let i = 0; i < arr.length; i++) {
      if (preAddress != arr[i].address) {
        result.push(arr[i])
      }
      preAddress = arr[i].address
    }
    return result
  }

  public static  verifyAsIpAddress( host:string):boolean {
      if(StringUtil.isEmpty(host)){
          return false
      }
      let matchResult:RegExpMatchArray=host.match(Utils.VERIFY_AS_IP_ADDRESS)
      if(!!!matchResult||matchResult==undefined||matchResult.length==0){
          return false
      }
    return true
  }

    //统计 10F: 或者:10B的个数

    public static cLength(str){

        var reg = /([0-9a-f]{1,4}:)|(:[0-9a-f]{1,4})/gi;

        var temp = str.replace(reg,' ');

        return temp.length;

    }

    /*
    * 判断ipv6格式
    * */
    public static isIPv6(tmpstr)  {
        //CDCD:910A:2222:5498:8475:1111:3900:2020
        var patrn=/^([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}$/i;
        var r=patrn.test(tmpstr)
        if(r)  {
            return true;
        }
        if(tmpstr=="::"){
            return true;
        }

        //F:F:F::1:1 F:F:F:F:F::1 F::F:F:F:F:1格式
        patrn=/^(([0-9a-f]{1,4}:){0,6})((:[0-9a-f]{1,4}){0,6})$/i;
        r=patrn.test(tmpstr);
        if(r)  {
            var c=Utils.cLength(tmpstr);
            if(c<=7 && c>0) {
                return true;
            }
        }

        //F:F:10F::
        patrn=/^([0-9a-f]{1,4}:){1,7}:$/i;
        r=patrn.test(tmpstr);
        if(r)   {
            return true;
        }

        //::F:F:10F
        patrn=/^:(:[0-9a-f]{1,4}){1,7}$/i;
        r=patrn.test(tmpstr);
        if(r)  {
            return true;
        }

        //F:0:0:0:0:0:10.0.0.1格式
        patrn=/^([0-9a-f]{1,4}:){6}(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/i;
        r=patrn.test(tmpstr);
        if(r)  {
            if(r[2]<=255 && r[3]<=255 &&r[4]<=255 && r[5]<=255 )
                return true;
        }

        //F::10.0.0.1格式
        patrn=/^([0-9a-f]{1,4}:){1,5}:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/i;
        r=patrn.test(tmpstr);
        if(r)   {
            if(r[2]<=255 && r[3]<=255 &&r[4]<=255 && r[5]<=255 )
                return true;
        }

        //::10.0.0.1格式
        patrn=/^::(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/i;
        r=patrn.test(tmpstr);
        if(r) {
            if(r[1]<=255 && r[2]<=255 &&r[3]<=255 && r[4]<=255)
                return true;
        }
        return false;
    }
}

